﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Dynamic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows.Forms;
using ContractManager.BLL.Business;
using ContractManager.Common.Class;
using ContractManager.Common.FormBase;
using ContractManager.Entity;
using DevExpress.Utils;
using DevExpress.XtraBars;
using DevExpress.XtraEditors;
using DevExpress.XtraEditors.Controls;
using DevExpress.XtraEditors.Repository;
using DevExpress.XtraGrid;
using DevExpress.XtraGrid.Views.Base;
using DevExpress.XtraGrid.Views.Grid;
using DevExpress.XtraLayout;
using DevExpress.XtraLayout.Utils;

namespace ContractManager.Lists.Forms
{
    public partial class FrmDynamicBase : XtraFormBase
    {
        #region "Private Variable"

        public List<GridControl> ListGridControl = new List<GridControl>();
        readonly CustomValidation _myvalidation = new CustomValidation();
        readonly List<string> _listFieldNumberHasEvent = new List<string>();
        readonly List<string> _listFieldLookupHasEvent = new List<string>();
        

        public int MasterId;
        public bool OnlyView;
        public bool SaveClose;
        public bool SaveNew;

        private LayoutControlItem _lastItem;
        private List<FieldTables> _list;
        private List<FieldTables> _listGrid;
        public List<RepositoryItemSearchLookUpEdit> ListSearchLookupEdit = new List<RepositoryItemSearchLookUpEdit>();
        public string KeyFieldName { get; set; }
        public string GetByMasterSql { get; set; }
        public string DeleteByMasterSql { get; set; }

        private LayoutControlItem LastItem
        {
            get { return _lastItem; }
        }

        #endregion

        #region "Form Construction"

        public FrmDynamicBase()
        {
            InitializeComponent();
        }

        #endregion

        #region "Private Method"

        private void BlankForm()
        {
            ResetControls();
        }

        private void CreateLayoutForms()
        {
            _list = ClsFieldTables.SelectByForm(FormNo);
            _listGrid = _list.Where(e => e.FieldTalbeType == 6).ToList();
            CreateControlDynamic(_list);
        }

        /// <summary>
        ///     Phương thức tạo điều khiển động
        /// </summary>
        /// <param name="list"></param>
        private void CreateControlDynamic(List<FieldTables> list)
        {
            var listGrid = new List<GridView>();
            layoutControl.BeginUpdate();
            foreach (FieldTables field in list)
            {
                string controlName = field.FieldTableName;
                string controlDisplay = field.FieldTableDescription;
                string controlFormual = field.FieldTableFormula;
                string controlGridLayout = field.GridLayoutName;
                string parentValueMember = field.ParentValueMember;
                string displayMember = field.DisplayMember;
                string valueMember = field.ValueMember;
                string validateExpress = field.ValidateExpress;
                int typeId = Convert.ToInt32(field.FieldTalbeType);
                var item = new LayoutControlItem {Text = controlDisplay};
                switch (typeId)
                {
                    case 1: //TextEdit
                        var txtTextEdit = new TextEdit {Name = controlName};
                        txtTextEdit.Properties.ReadOnly = Convert.ToBoolean(field.FieldTableReadOnly);
                        txtTextEdit.TabStop = !Convert.ToBoolean(field.FieldTableIsTabStop);
                        layoutControl.AddItem(item, LastItem, InsertType.Bottom);
                        item.Control = txtTextEdit;
                        _lastItem = item;
                        item.Name = "item" + controlName;
                        item.Height = 25;
                        break;
                    case 2: //Memo Edit
                        var txtMemoEdit = new MemoEdit {Name = controlName};
                        txtMemoEdit.Properties.ReadOnly = Convert.ToBoolean(field.FieldTableReadOnly);
                        txtMemoEdit.TabStop = !Convert.ToBoolean(field.FieldTableIsTabStop);
                        layoutControl.AddItem(item, LastItem, InsertType.Bottom);
                        item.Control = txtMemoEdit;
                        _lastItem = item;
                        item.Name = "item" + controlName;
                        item.Height = 25;
                        break;
                    case 3: //CalcEdit
                        var txtCalcEdit = new CalcEdit {Name = controlName};
                        txtCalcEdit.Properties.ReadOnly = Convert.ToBoolean(field.FieldTableReadOnly);
                        txtCalcEdit.TabStop = !Convert.ToBoolean(field.FieldTableIsTabStop);
                        txtCalcEdit.Properties.Mask.EditMask = @"n0";
                        txtCalcEdit.Properties.Mask.UseMaskAsDisplayFormat = true;
                        txtCalcEdit.StyleController = layoutControl;
                        layoutControl.AddItem(item, LastItem, InsertType.Bottom);
                        item.Control = txtCalcEdit;
                        _lastItem = item;
                        item.Name = "item" + controlName;
                        item.Height = 25;
                        break;
                    case 4: //DateTime
                        var txtDateEdit = new DateEdit {Name = controlName};
                        txtDateEdit.Properties.ReadOnly = Convert.ToBoolean(field.FieldTableReadOnly);
                        txtDateEdit.TabStop = !Convert.ToBoolean(field.FieldTableIsTabStop);
                        txtDateEdit.Properties.CalendarTimeProperties.CloseUpKey = new KeyShortcut(Keys.F4);
                        txtDateEdit.Properties.CalendarTimeProperties.PopupBorderStyle = PopupBorderStyles.Default;
                        txtDateEdit.Properties.Mask.EditMask = @"dd/MM/yyyy";
                        txtDateEdit.Properties.Mask.UseMaskAsDisplayFormat = true;
                        txtDateEdit.StyleController = layoutControl;
                        layoutControl.AddItem(item, LastItem, InsertType.Bottom);
                        item.Control = txtDateEdit;
                        _lastItem = item;
                        item.Name = "item" + controlName;
                        item.Height = 25;
                        break;
                    case 5: //Lookup Edit
                        DataTable dvDropDown = ClsSourceData.GetControlDataBySourceId(field.SourceDataId, "");
                        var slupDropDown = new SearchLookUpEdit {Name = controlName};
                        slupDropDown.Properties.ReadOnly = Convert.ToBoolean(field.FieldTableReadOnly);
                        slupDropDown.TabStop = !Convert.ToBoolean(field.FieldTableIsTabStop);
                        slupDropDown.Properties.View.OptionsBehavior.AutoPopulateColumns = false;
                        slupDropDown.Properties.View.OptionsView.ColumnAutoWidth = false;
                        slupDropDown.Properties.DataSource = null;
                        slupDropDown.Properties.DataSource = dvDropDown;
                        slupDropDown.Properties.DisplayMember = displayMember;
                        slupDropDown.Properties.ValueMember = valueMember;
                        slupDropDown.Properties.NullText = "";
                        slupDropDown.Properties.PopupFormWidth = 350;
                        layoutControl.AddItem(item, LastItem, InsertType.Bottom);
                        item.Control = slupDropDown;
                        _lastItem = item;
                        item.Name = "item" + controlName;
                        item.Height = 25;
                        if (!String.IsNullOrEmpty(controlGridLayout))
                        {
                            string fileLayout = ClsVariable.GetRestoreLayoutFullPath(controlGridLayout);
                            slupDropDown.Properties.View.RestoreLayoutFromXml(fileLayout, OptionsLayoutBase.FullLayout);
                        }
                        if (field.FieldHasEvents == true)
                        {
                            slupDropDown.EditValueChanged += slupDropDown_EditValueChanged;
                        }
                        break;
                    case 6: //Grid
                        var source = ClsSourceData.SelectByPk(Convert.ToInt32(field.SourceDataId)).SourceDataValue;
                        string sql = String.Format("{0} WHERE {1}={2}", source,
                            this.Form_TableKeyField, MasterId);
                        DataTable dvGrid = ClsSourceData.GetGridDataBySourceId(sql, "");
                        var grdDynamic = new GridControl {Name = controlName, UseEmbeddedNavigator = true};
                        var gridStatusGridView = new GridView();
                        grdDynamic.MainView = gridStatusGridView;
                        gridStatusGridView.Name = "grv" + controlName;
                        gridStatusGridView.GridControl = grdDynamic;
                        grdDynamic.ViewCollection.AddRange(new BaseView[]
                        {
                            gridStatusGridView
                        });
                       
                        //grdDynamic.ForceInitialize();
                        layoutControl.AddItem(item, LastItem, InsertType.Bottom);
                        item.Control = grdDynamic;
                        _lastItem = item;
                        item.Name = "item" + controlName;
                        item.Height = 50;

                        #region "Add RepositoryItem"

                        //Add control Calc percent
                        var repositoryItemPercentCalcEdit = new RepositoryItemCalcEdit();
                        repositoryItemPercentCalcEdit.AutoHeight = false;
                        repositoryItemPercentCalcEdit.Mask.EditMask = @"p";
                        repositoryItemPercentCalcEdit.Mask.UseMaskAsDisplayFormat = true;
                        repositoryItemPercentCalcEdit.Name = "repositoryItemPercentCalcEdit1";

                        //Add control Calc Number
                        var repositoryItemNumberCalcEdit = new RepositoryItemCalcEdit();
                        repositoryItemNumberCalcEdit.AutoHeight = false;
                        
                        repositoryItemNumberCalcEdit.Mask.EditMask = @"n0";
                        repositoryItemNumberCalcEdit.Mask.UseMaskAsDisplayFormat = true;
                        repositoryItemNumberCalcEdit.Name = "repositoryItemNumberCalcEdit1";
                        //Add control Date Number
                        var repositoryItemDateEdit = new RepositoryItemDateEdit();
                        repositoryItemDateEdit.AutoHeight = false;
                        
                        repositoryItemDateEdit.CalendarTimeProperties.CloseUpKey = new KeyShortcut(Keys.F4);
                        repositoryItemDateEdit.CalendarTimeProperties.PopupBorderStyle = PopupBorderStyles.Default;
                        repositoryItemDateEdit.Mask.EditMask = @"dd/MM/yyyy";
                        repositoryItemDateEdit.Mask.UseMaskAsDisplayFormat = true;
                        repositoryItemDateEdit.Name = "repositoryItemDateEdit";
                        //Add control Memo Edit RepositoryItemMemoEdit
                        var repositoryItemMemoEdit = new RepositoryItemMemoEdit();
                        repositoryItemDateEdit.Name = "RepositoryItemMemoEdit";

                        #endregion

                        #region "Add Control to Grid"
                        grdDynamic.RepositoryItems.Add(repositoryItemPercentCalcEdit);
                        grdDynamic.RepositoryItems.Add(repositoryItemNumberCalcEdit);
                        grdDynamic.RepositoryItems.Add(repositoryItemDateEdit);
                        grdDynamic.RepositoryItems.Add(repositoryItemMemoEdit);
                        #endregion

                        #region "Get list control Lookup for Grid form Data Source"

                        List<FieldTableDetails> listDetails = ClsFieldTables.SelectDetails(field.FieldTableId);
                        foreach (FieldTableDetails detail in listDetails)
                        {
                            var repositoryItemSearchLookUpEdit = new RepositoryItemSearchLookUpEdit
                            {
                                Name = String.Format("RepositoryItemSearchLookUpEdit{0}{1}",
                                    field.FieldTableName, detail.FieldTableDetailId),
                                AutoHeight = false
                            };

                            string where = detail.FieldTableDetailHasEvent == true ? " WHERE 1=0" : "";
                            DataTable dvLookup = ClsSourceData.GetControlDataBySourceId(detail.SourceDataId, where);
                            repositoryItemSearchLookUpEdit.DataSource = dvLookup;
                            repositoryItemSearchLookUpEdit.DisplayMember = detail.DisplayMember;
                            repositoryItemSearchLookUpEdit.ValueMember = detail.ValueMember;
                            repositoryItemSearchLookUpEdit.NullText = "";
                            var repositoryItemSearchLookUpGridView = new GridView
                            {
                                FocusRectStyle = DrawFocusRectStyle.RowFocus,
                                Name = String.Format("RepositoryItemSearchLookUpGridView{0}", field.FieldTableName)
                            };
                            if (!String.IsNullOrEmpty(detail.FieldTableLayout))
                            {
                                string fileLayout = ClsVariable.GetRestoreLayoutFullPath(detail.FieldTableLayout);
                                repositoryItemSearchLookUpGridView.RestoreLayoutFromXml(fileLayout,
                                    OptionsLayoutBase.FullLayout);
                            }
                            repositoryItemSearchLookUpEdit.View = repositoryItemSearchLookUpGridView;

                            grdDynamic.RepositoryItems.Add(repositoryItemSearchLookUpEdit);
                            ListSearchLookupEdit.Add(repositoryItemSearchLookUpEdit);
                        }

                        #endregion

                        #region "Load layout to Grid View"

                        if (!String.IsNullOrEmpty(controlGridLayout))
                        {
                            string fileLayout = ClsVariable.GetRestoreLayoutFullPath(controlGridLayout);
                            gridStatusGridView.RestoreLayoutFromXml(fileLayout, OptionsLayoutBase.FullLayout);
                        }

                         grdDynamic.DataSource = null;
                        grdDynamic.DataSource = dvGrid;

                        #endregion

                        #region "Check control has event value change"

                        if (field.FieldHasEvents == true)
                        {
                            gridStatusGridView.CellValueChanged += gridStatusGridView_CellValueChanged;
                        }

                        #endregion

                        listGrid.Add(gridStatusGridView);
                        ListGridControl.Add(grdDynamic);
                        break;
                }
            }

            layoutControl.BestFit();
            layoutControl.EndUpdate();
        }

        private ExpandoObject GetDynamicSqlValue(List<FieldTables> list)
        {
            dynamic ret = new ExpandoObject();
            FieldTables item =
                list.FirstOrDefault(
                    e => e.FieldTableKeyField != null && String.Format("{0}", e.FieldTableKeyField).Length > 0);
           
            string keyField = String.Format("{0}", item.FieldTableKeyField);
            ((IDictionary<String, Object>) ret).Add(keyField, MasterId);
            list = list.Where(op => op.FieldTalbeType != 6 && op.FieldTableReadOnly==false).ToList();

            foreach (FieldTables field in list)
            {
                string controlName = field.FieldTableName;
                if (controlName.Equals(field.FieldTableKeyField)) continue;
                int typeId = Convert.ToInt32(field.FieldTalbeType);

                if (typeId == 1 || typeId == 2)
                {
                    string sret = GetTextValue(controlName, typeId);
                    ((IDictionary<String, Object>) ret).Add(controlName, sret);
                }
                else if (typeId == 3)
                {
                    decimal dret = GetNumberValue(controlName);
                    ((IDictionary<String, Object>) ret).Add(controlName, dret);
                }
                else if (typeId == 4)
                {
                    DateTime? dtret = GetDateValue(controlName);
                    ((IDictionary<String, Object>) ret).Add(controlName, dtret);
                }

                else if (typeId == 5)
                {
                    int? itret = GetLookupValue(controlName);
                    ((IDictionary<String, Object>) ret).Add(controlName, itret);
                }
                else if (typeId == 7)
                {
                    byte[] btret = GetImageValue(controlName);
                    ((IDictionary<String, Object>)ret).Add(controlName, btret);
                }
                else
                {
                    ((IDictionary<String, Object>) ret).Add(controlName, DBNull.Value);
                }
            }

            return ret;
        }

        private ExpandoObject GetDynamicDetailSqlValue(List<FieldTables> list)
        {
            dynamic ret = new ExpandoObject();
            FieldTables item =
                list.FirstOrDefault(
                    e => e.FieldTableKeyField != null && String.Format("{0}", e.FieldTableKeyField).Length > 0);
            Entity.Forms from = ClsForms.SelectByPk(FormNo);

            string keyField = String.Format("{0}", item.FieldTableKeyField);
            ((IDictionary<String, Object>)ret).Add(keyField, MasterId);
            list = list.Where(op => op.FieldTalbeType == 6).ToList();

            foreach (FieldTables field in list)
            {
                string controlName = field.FieldTableName;
                if (controlName.Equals(field.FieldTableKeyField)) continue;
                
                    DataTable dtret = GetGridValue(controlName);
                    ((IDictionary<String, Object>)ret).Add(controlName, dtret);
                
            }

            return ret;
        }

        private string GetTextValue(string controlName, int typeId)
        {
            string ret = "";
            foreach (Control ctrl in layoutControl.Controls.Cast<Control>().Where(ctrl => ctrl.Name.Equals(controlName))
                )
            {
                ret = typeId == 1
                    ? String.Format("{0}", ((TextEdit) ctrl).EditValue)
                    : (typeId == 2 ? String.Format("{0}", ((MemoEdit) ctrl).EditValue) : "");
            }
            return ret;
        }

        private decimal GetNumberValue(string controlName)
        {
            decimal ret = 0;
            foreach (Control ctrl in layoutControl.Controls.Cast<Control>().Where(ctrl => ctrl.Name.Equals(controlName))
                )
            {
                ret = ((CalcEdit) ctrl).Value;
            }
            return ret;
        }

        private DateTime? GetDateValue(string controlName)
        {
            foreach (Control ctrl in layoutControl.Controls.Cast<Control>().Where(ctrl => ctrl.Name.Equals(controlName))
                )
            {
                return (DateTime?) ((DateEdit) ctrl).EditValue;
            }
            return null;
        }

        private int? GetLookupValue(string controlName)
        {
            foreach (Control ctrl in layoutControl.Controls.Cast<Control>().Where(ctrl => ctrl.Name.Equals(controlName))
                )
            {
                return (int?) ((SearchLookUpEdit) ctrl).EditValue;
            }
            return null;
        }

        private byte[] GetImageValue(string controlName)
        {
            return layoutControl.Controls.Cast<Control>().Where(ctrl => ctrl.Name.Equals(controlName)).Select(ctrl => (byte[]) ((PictureEdit) ctrl).EditValue).FirstOrDefault();
        }

        private DataTable GetGridValue(string controlName)
        {

            foreach (Control ctrl in layoutControl.Controls.Cast<Control>().Where(ctrl => ctrl.Name.Equals(controlName))
                )
            {
                var grdDetail = ctrl as GridControl;
                if (grdDetail != null)
                {
                    grdDetail.EmbeddedNavigator.Buttons.DoClick(grdDetail.EmbeddedNavigator.Buttons.EndEdit);
                    return (DataTable)grdDetail.DataSource;
                }
                
            }
            return null;
        }

        private Control GetControlByName(string controlName)
        {
            return layoutControl.Controls.Find(controlName, true).FirstOrDefault();
        }

        private void GetDetail()
        {
            var data = new DataTable();
            if (!String.IsNullOrEmpty(Form_Detail_SqlDeleteByMaster))
            {
                Form_Detail_SqlDeleteByMaster = String.Format("{0} WHERE {1}={2}", Form_Detail_SqlDeleteByMaster, Form_TableKeyField, MasterId);
                data = ClsDynamic.GetObject(Form_Detail_SqlDeleteByMaster);
            }
            if (data.Rows.Count > 0)
            {
                DataRow row = data.Rows[0];
                var listControl = _list.Where(op => op.FieldTableReadOnly == false).ToList();
                foreach (FieldTables field in listControl)
                {
                    string controlName = field.FieldTableName;
                    int typeId = Convert.ToInt32(field.FieldTalbeType);
                    switch (typeId)
                    {
                        case 1: //TextEdit
                            var textEdit = GetControlByName(controlName) as TextEdit;
                            if (textEdit != null) textEdit.EditValue = row[controlName];
                            break;
                        case 2: //Memo Edit
                            var memoEdit = GetControlByName(controlName) as MemoEdit;
                            if (memoEdit != null) memoEdit.EditValue = row[controlName];
                            break;
                        case 3: //CalcEdit
                            var calcEdit = GetControlByName(controlName) as CalcEdit;
                            if (calcEdit != null) calcEdit.EditValue = row[controlName];
                            break;
                        case 4: //DateTime
                            var dateEdit = GetControlByName(controlName) as DateEdit;
                            if (dateEdit != null) dateEdit.EditValue = row[controlName];
                            break;
                        case 5: //Lookup Edit
                            var lookupEdit = GetControlByName(controlName) as SearchLookUpEdit;
                            if (lookupEdit != null) lookupEdit.EditValue = row[controlName];
                            break;
                        case 7: //PictureEdit
                            var pictureEdit = GetControlByName(controlName) as PictureEdit;
                            if (pictureEdit != null) pictureEdit.EditValue = row[controlName];
                            break;
                    }
                }
            }
        }

        private void DoSave()
        {
            #region "Check Validate"

            if (!this.OperateValidate())
            {
                XtraMessageBox.Show("Vui lòng nhập đầy đủ thông tin trước khi lưu", "Thông báo", MessageBoxButtons.OK,
                    MessageBoxIcon.Warning);
                return;
            }
            #endregion
            dynamic data = GetDynamicSqlValue(_list);
            dynamic dataDetail = GetDynamicDetailSqlValue(_list);
            Entity.Forms form = ClsForms.SelectByPk(FormNo);
            try
            {
                if (MasterId > 0)
                {
                    if (form.Form_IsBusiness == true)
                    {
                        ((IDictionary<String, Object>) data).Add("UpdateBy", ClsVariable.EmployeeId);
                        ((IDictionary<String, Object>) data).Add("UpdateDate", DateTime.Now);
                    }

                    ClsDynamic.UpdateObject(TableName, Form_TableKeyField, data,dataDetail, _listGrid,this.FormNo);
                }
                else
                {
                    if (form.Form_IsBusiness == true)
                    {
                        ((IDictionary<String, Object>) data).Add("FormId", FormNo);
                        ((IDictionary<String, Object>) data).Add("VoucherCate", VoucherCate);

                        ((IDictionary<String, Object>) data).Add("CreateBy", ClsVariable.EmployeeId);
                        ((IDictionary<String, Object>) data).Add("CreateDate", DateTime.Now);
                    }
                    ClsDynamic.InsertObject(TableName, Form_TableKeyField, data, dataDetail, _listGrid, this.FormNo);
                
                }
                if (SaveNew)
                {
                    MasterId = 0;
                    BlankForm();
                }
                else if (SaveClose)
                {
                    Close();
                }
            }
            catch (Exception exception)
            {
                MessageBox.Show(exception.Message);
            }
        }

        private void DoDelete()
        {
            dynamic data = new ExpandoObject();
            ((IDictionary<String, Object>) data).Add(Form_TableKeyField, MasterId);
            try
            {
                ClsDynamic.DeleteObject(Form_TableName, Form_TableKeyField, data,this.FormNo);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        #endregion

        #region "PostFix"
        public static int GetPriority(string op)
        {
            if (op == "*" || op == "/" || op == "%")
                return 2;
            if (op == "+" || op == "-")
                return 1;
            return 0;
        }

        public static void FormatExpression(ref string expression)
        {
            expression = expression.Replace(" ", "");
            expression = Regex.Replace(expression, @"\+|\-|\*|\/|\%|\^|\)|\(", delegate(Match match)
            {
                return " " + match.Value + " ";
            });
            expression = expression.Replace("  ", " ");
            expression = expression.Trim();
        }

        private static bool IsOperator(string str)
        {
            return Regex.Match(str, @"\+|\-|\*|\/|\%").Success;
        }

        public static bool IsOperand(string str)
        {
            return Regex.Match(str, @"^\d+$|([a-z]|[A-Z])$").Success;
            // return Regex.Match(str, @"([a-z]|[A-Z])$").Success;
        }

        public static string Infix2Postfix(string infix)
        {
            FormatExpression(ref infix);
            IEnumerable<string> str = infix.Split(' ');
            Stack<string> stack = new Stack<string>();
            StringBuilder postfix = new StringBuilder();
            foreach (string s in str)
            {
                if (IsOperand(s))
                    postfix.Append(s).Append(" ");
                else if (s == "(")
                    stack.Push(s);
                else if (s == ")")
                {
                    string x = stack.Pop();
                    while (x != "(")
                    {
                        postfix.Append(x).Append(" ");
                        x = stack.Pop();
                    }
                }
                else// IsOperator(s)
                {
                    while (stack.Count > 0 && GetPriority(s) <= GetPriority(stack.Peek()))
                        postfix.Append(stack.Pop()).Append(" ");
                    stack.Push(s);
                }
            }
            while (stack.Count > 0)
                postfix.Append(stack.Pop()).Append(" ");
            return postfix.ToString();
        }

        public void EvaluatePostfix(string postfix, string fieldName, GridView view,string currentFieldName, object currentValue)
        {
            decimal num;
            Stack<decimal> stack = new Stack<decimal>();
            postfix = postfix.Trim();
            IEnumerable<string> enumer = postfix.Split(' ');
            foreach (string s in enumer)
            {
                if (IsOperand(s))
                {
                    if (decimal.TryParse(s, out num))
                    {
                        stack.Push(decimal.Parse(s));
                    }
                    else
                    {
                        string fName = s;
                        if (!String.IsNullOrEmpty(fName))
                        {
                            decimal value = 0;
                            if (fName.Equals(currentFieldName))
                            {
                                value = Convert.ToDecimal(currentValue);
                            }
                            else
                            {
                                if (view.GetRowCellValue(view.FocusedRowHandle, fName) == null
                                    || view.GetRowCellValue(view.FocusedRowHandle, fName) == DBNull.Value)
                                {
                                    value = 0;
                                }
                                else
                                {
                                    value = Convert.ToDecimal(view.GetRowCellValue(view.FocusedRowHandle, fName));
                                }
                                //value = view.GetRowCellValue(view.FocusedRowHandle, fName) == null
                                //         || view.GetRowCellValue(view.FocusedRowHandle, fName) == DBNull.Value
                                //    ? 0
                                //    : Convert.ToDecimal(view.GetRowCellValue(view.FocusedRowHandle, fName));
                            }
                             
                            //decimal value = view.GetRowCellValue(view.FocusedRowHandle, fName) == null
                            //|| view.GetRowCellValue(view.FocusedRowHandle, fName) == DBNull.Value ? 0 :
                            //            Convert.ToDecimal(view.GetRowCellValue(view.FocusedRowHandle, fName));
                            stack.Push(value);
                        }
                    }
                }
                else
                {
                    decimal x = stack.Pop();
                    decimal y = stack.Pop();
                    switch (s)
                    {
                        case "+": y += x; break;
                        case "-": y -= x; break;
                        case "*": y *= x; break;
                        case "/": y /= x; break;
                        case "%": y %= x; break;
                    }
                    stack.Push(y);
                }
            }
            var ret = stack.Pop();
            view.SetRowCellValue(view.FocusedRowHandle, fieldName, ret);
            // return stack.Pop();
        }
        #endregion

        #region "Validate"
        private List<ControlRule> GetRuleList()
        {
            var rulelist = new List<ControlRule>();
            var listControlRule = _list.Where(op => op.FieldTalbeType != 6 && op.FieldTalbeIsValidate==true).ToList();
            foreach (var rule in listControlRule)
            {
                Control ctr = GetControlByName(rule.FieldTableName);
                //Not Emptype
                if (rule.FieldTableValidateType == 1)
                {
                    rulelist.Add(new ControlRule(ctr, ControlRule.NotEmpty()));
                }
                //GreateOrEqual Number
                else if (rule.FieldTableValidateType == 2)
                {
                    rulelist.Add(new ControlRule(ctr, ControlRule.NoLessNumber(Convert.ToDecimal(rule.FieldTableValidateToNumber))));
                }
                //Greate Number
                else if (rule.FieldTableValidateType == 3)
                {
                    rulelist.Add(new ControlRule(ctr, ControlRule.GreaterNumber(Convert.ToDecimal(rule.FieldTableValidateFromNumber))));
                }
                    //Between Number
                else if (rule.FieldTableValidateType == 4)
                {
                    rulelist.Add(new ControlRule(ctr, ControlRule.BetweenNumbers(Convert.ToDecimal(rule.FieldTableValidateFromNumber), Convert.ToDecimal(rule.FieldTableValidateToNumber))));
                }
                //between Date
                else if (rule.FieldTableValidateType == 5)
                {
                    DateTime from = Convert.ToDateTime(rule.FieldTableValidateFromDate);
                    DateTime to = Convert.ToDateTime(rule.FieldTableValidateToDate);
                    rulelist.Add(new ControlRule(ctr, ControlRule.BetweenDate(from,to)));
                }
            }

            return rulelist;
        }

        private bool OperateValidate()
        {
            bool flag = true;
            _myvalidation.RuleList = GetRuleList();
            if (!_myvalidation.Validate())
            {
                flag = false;
            }
            return flag;
        }
        #endregion

        #region "Form Event"

        private void FrmDynamicBaseLoad(object sender, EventArgs e)
        {
            CreateLayoutForms();
            BlankForm();
            if (!String.IsNullOrEmpty(FormXtraLayoutTemplate))
            {
                string fileLayout = ClsVariable.GetRestoreLayoutFullPath(FormXtraLayoutTemplate);
                layoutControl.RestoreLayoutFromXml(fileLayout);
            }
            if (MasterId > 0) GetDetail();
            btnSaveNew.Enabled = !OnlyView;
            btnSave.Enabled = !OnlyView;
            btnSaveClose.Enabled = !OnlyView;
            btnDelete.Enabled = !OnlyView;
            btnDesign.Enabled = !OnlyView;
        }

        #endregion

        #region "Toolbar Event"

        private void TbMenuItemClick(object sender, ItemClickEventArgs e)
        {
            switch (e.Item.Name)
            {
                case "btnSave":
                    DoSave();
                    break;
                case "btnSaveNew": //Lưu và thêm mới
                    SaveNew = true;
                    SaveClose = false;
                    DoSave();
                    break;
                case "btnSaveClose": //Lưu và đóng
                    SaveClose = true;
                    SaveNew = false;
                    DoSave();
                    break;
                case "btnDelete":
                    DoDelete();
                    break;
                case "btnDesign":
                    ClsVariable.ShowDesignXtraGrid(ListGridControl[0]);
                    break;
                case "btnRefresh": //Nạp lại danh mục
                    break;
                case "btnHistory": //History
                    break;
                case "btnClose":
                    Close();
                    break;
            }
        }

        #endregion

        #region "Lookup Event"
        private void slupDropDown_EditValueChanged(object sender, EventArgs e)
        {
            var lookup = sender as SearchLookUpEdit;
            var dataSource = lookup.Properties.DataSource as DataTable;
            DataView dvSource = dataSource.DefaultView;
            short id = Convert.ToInt16(lookup.EditValue);

            #region "Get Data Master Form Object"
            List<FieldTables> listControl = _list.Where(p => p.ParentValueMember.Equals(lookup.Name) && p.FieldTalbeType!=6).ToList();
            foreach (FieldTables item in listControl)
            {
                Control ctr = layoutControl.Controls.Find(item.FieldTableName, true).FirstOrDefault();
                var textEdit = ctr as TextEdit;
                var dateEdit = ctr as DateEdit;
                var memoEdit = ctr as MemoEdit;
                var calcEdit = ctr as CalcEdit;
                var searchLookUpEdit = ctr as SearchLookUpEdit;
                //Neu la search lookup thi ta bind lai du lieu cho dieu khien
                if (searchLookUpEdit != null)
                {
                    FieldTables listSearch =
                        _list.FirstOrDefault(
                            op => op.FieldTableName == searchLookUpEdit.Name && op.FormNo == this.FormNo);
                    if (listSearch != null)
                    {
                        string where = String.Format(" WHERE {0}={1}", lookup.Properties.ValueMember, id);
                        var dtLookup = ClsSourceData.GetControlDataBySourceId(listSearch.SourceDataId, where);
                        ((SearchLookUpEdit) ctr).Properties.DataSource = dtLookup;
                        ((SearchLookUpEdit) ctr).Properties.ValueMember = listSearch.ValueMember;
                        ((SearchLookUpEdit) ctr).Properties.DisplayMember = listSearch.DisplayMember;
                    }
                }
                else
                {
                    //Get data source
                    dvSource.RowFilter = String.Format("{0}={1}", lookup.Properties.ValueMember, id);
                    object value = null;
                    if (dvSource.Count > 0)
                    {
                        value = dvSource[0][item.FieldTableName];
                    }
                    if (textEdit != null)
                        ((TextEdit)ctr).EditValue = value;
                    if (dateEdit != null)
                        ((DateEdit)ctr).EditValue = value;
                    if (memoEdit != null)
                        ((MemoEdit)ctr).EditValue = value;
                    if (calcEdit != null)
                        ((CalcEdit)ctr).EditValue = value;
                }
                
                
                
                
                


                dvSource.RowFilter = "";
            }

            #endregion

            #region "Get Data for Lookup on Grid"

            FieldTables fieldTableId =
                _list.FirstOrDefault(o => o.ParentValueMember == lookup.Name && o.FormNo == FormNo && o.FieldTalbeType==6);
            if (fieldTableId != null)
            {
                List<FieldTableDetails> listDetails = ClsFieldTables.SelectDetails(fieldTableId.FieldTableId);
                foreach (FieldTableDetails detail in listDetails)
                {
                    string controlName = String.Format("RepositoryItemSearchLookUpEdit{0}{1}", fieldTableId.FieldTableName, detail.FieldTableDetailId);
                    RepositoryItemSearchLookUpEdit lookupCtr =
                        ListSearchLookupEdit.FirstOrDefault(p => p.Name == controlName);
                    string where = String.Format(" WHERE {0}={1}", lookup.Properties.ValueMember, id);
                    DataTable dvLookup = ClsSourceData.GetControlDataBySourceId(detail.SourceDataId, where);
                    lookupCtr.DataSource = dvLookup;
                    lookupCtr.DisplayMember = detail.DisplayMember;
                    lookupCtr.ValueMember = detail.ValueMember;
                }
            }
            

            #endregion

            
        }
        #endregion

        #region "Grid Event"
        private void gridStatusGridView_CellValueChanged(object sender, CellValueChangedEventArgs e)
        {
            if (e.Value == null) return;
            var gridView = sender as GridView;
            string controlName = gridView.GridControl.Name;
            var list = _list.FirstOrDefault(op => op.FieldTableName == controlName && op.FormNo==this.FormNo);
            if (list == null) return;
            string[] arrListField = list.GridLayoutFieldWith.Split(',');
            string[] arrListFieldLookup = list.FieldTableListLookupChange.Split(',');

            _listFieldNumberHasEvent.AddRange(arrListField);
            _listFieldLookupHasEvent.AddRange(arrListFieldLookup);
            //foreach (string s in arrListField)
            //{
            //    _listFieldNumberHasEvent.Add(s);
            //}
            //foreach (var s in arrListFieldLookup)
            //{
            //    _listFieldLookupHasEvent.Add(s);
            //}
            
            if (_listFieldNumberHasEvent.Contains(e.Column.FieldName))
            {
                var listDetail = ClsFieldTables.SelectFormulaColumn(list.FieldTableId);
                //Duyệt tất cả các cột công thức có liên quan 
                foreach (var item in listDetail)
                {
                    string expression = item.FieldTableDetailFormula;
                    string postFix = Infix2Postfix(expression);
                    EvaluatePostfix(postFix, item.FieldTableDetailColumnName, gridView,e.Column.FieldName,e.Value);
                }
            }
            //Lay tat ca nhung cot cua Grid co loai =6 (Lookup) cua Grid hien tai
            if (!arrListFieldLookup.Contains(e.Column.FieldName)) return;
            var listLookup = ClsFieldTables.SelectDetails(list.FieldTableId);
            foreach (var lookup in listLookup)
            {
                //Lay data source cua loai = 6
                string where = String.Format(" WHERE {0}={1}", e.Column.FieldName, e.Value);
                var dataSource = ClsSourceData.GetControlDataBySourceId(lookup.SourceDataId, @where);
                if (dataSource == null || dataSource.Rows.Count <= 0) continue;
                var row = dataSource.Rows[0];
                //Lay tat ca cac cot lien quan co parent = FieldName
                var listColumn = ClsFieldTables.SelectDetails(list.FieldTableId, lookup.FieldTableDetailColumnName);

                foreach (var column in listColumn)
                {
                    gridView.SetRowCellValue(e.RowHandle, column.FieldTableDetailColumnName, row[column.FieldTableDetailColumnName]);
                }
            }
        }

        #endregion
    }
}